/****************************************************************************
 * Copyright (C) 2009-2010 SciTouch LLC
 * 
 * This file is part of Indigo toolkit.
 * 
 * This file may be distributed and/or modified under the terms of the
 * GNU General Public License version 3 as published by the Free Software
 * Foundation and appearing in the file LICENSE.GPL included in the
 * packaging of this file.
 * 
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 ***************************************************************************/

#include <time.h>
#include "reaction/reaction.h"
#include "reaction/rxnfile_saver.h"

RxnfileSaver::RxnfileSaver(Output &output) : 
   highlighting(0),
   v2000(false),
   _output(output)
{
}

RxnfileSaver::~RxnfileSaver(){
}

void RxnfileSaver::saveReaction(Reaction &reaction){

   MolfileSaver molfileSaver(_output);
   molfileSaver.v2000 = v2000;
   
   _writeRxnHeader(reaction.reactantsCount(), reaction.productsCount());

   _writeReactantsHeader();

   for (int i = reaction.reactantBegin(); i < reaction.reactantEnd(); i = reaction.reactantNext(i) )
   {
      _writeMolHeader();
      if(highlighting != 0)
         molfileSaver.highlighting = &highlighting->getGraphHighlighting(i);
      _writeMol(molfileSaver, reaction, i);
   }

   _writeReactantsFooter();
   _writeProductsHeader();

   for (int i = reaction.productBegin(); i < reaction.productEnd(); i = reaction.productNext(i))
   {
      _writeMolHeader();
      if(highlighting != 0)
         molfileSaver.highlighting = &highlighting->getGraphHighlighting(i);
      _writeMol(molfileSaver, reaction, i);
   }

   _writeProductsFooter();
   _writeRxnFooter();
}

void RxnfileSaver::saveQueryReaction(Reaction &reaction){

   MolfileSaver molfileSaver(_output);
   molfileSaver.v2000 = v2000;
   _writeRxnHeader(reaction.reactantsCount(), reaction.productsCount());

   _writeReactantsHeader();

   for (int i = reaction.reactantBegin(); i < reaction.reactantEnd(); i = reaction.reactantNext(i) )
   {
      _writeMolHeader();
      if(highlighting != 0)
         molfileSaver.highlighting = &highlighting->getGraphHighlighting(i);
      _writeQueryMol(molfileSaver, reaction, i);
   }

   _writeReactantsFooter();
   _writeProductsHeader();

   for (int i = reaction.productBegin(); i < reaction.productEnd(); i = reaction.productNext(i))
   {
      _writeMolHeader();
      if(highlighting != 0)
         molfileSaver.highlighting = &highlighting->getGraphHighlighting(i);
      _writeQueryMol(molfileSaver, reaction, i);
   }

   _writeProductsFooter();
   _writeRxnFooter();
}

void RxnfileSaver::_writeRxnHeader(int reactantSize, int productSize)
{
   if (v2000)
      _output.writeStringCR("$RXN");
   else
      _output.writeStringCR("$RXN V3000");

   time_t tm = time(NULL);
   const struct tm *lt = localtime(&tm);

   _output.writeCR();
   _output.printfCR("  -BINGO- %02d%02d%02d%02d%02d", lt->tm_mon + 1, lt->tm_mday,
      lt->tm_year % 100, lt->tm_hour, lt->tm_min);
   _output.writeCR();

   if (v2000)
      _output.printf("%3d%3d\n", reactantSize, productSize);
   else
      _output.printf("M  V30 COUNTS %d %d\n", reactantSize, productSize);
}

void RxnfileSaver::_writeMolHeader ()
{
   if (v2000)
      _output.writeStringCR("$MOL");
}

void RxnfileSaver::_writeReactantsHeader ()
{
   if (!v2000)
      _output.writeStringCR("M  V30 BEGIN REACTANT");
}

void RxnfileSaver::_writeProductsHeader ()
{
   if (!v2000)
      _output.writeStringCR("M  V30 BEGIN PRODUCT");
}

void RxnfileSaver::_writeMol (MolfileSaver &saver, const Reaction& reaction, int index) {
   
   saver.reactionAtomMapping = &reaction.getAAMArray(index);
   saver.reactionAtomInversion = &reaction.getInversionArray(index);
   saver.reactionBondReactingCenter = &reaction.getReactingCenterArray(index);
   
   if (v2000)
      saver.saveMolecule(reaction.getMolecule(index));
   else
      saver.saveCtab3000(reaction.getMolecule(index));
}

void RxnfileSaver::_writeQueryMol (MolfileSaver &saver, const Reaction& reaction, int index) {

   saver.reactionAtomMapping = &reaction.getAAMArray(index);
   saver.reactionAtomInversion = &reaction.getInversionArray(index);
   saver.reactionBondReactingCenter = &reaction.getReactingCenterArray(index);
   saver.reactionAtomExactChange = &reaction.getExactChangeArray(index);
           
   if (v2000)
      saver.saveQueryMolecule(reaction.getMolecule(index));
   else
      saver.saveQueryCtab3000(reaction.getMolecule(index));
}

void RxnfileSaver::_writeReactantsFooter ()
{
   if (!v2000)
      _output.writeStringCR("M  V30 END REACTANT");
}

void RxnfileSaver::_writeProductsFooter ()
{
   if (!v2000)
      _output.writeStringCR("M  V30 END PRODUCT");
}

void RxnfileSaver::_writeRxnFooter ()
{
   if (!v2000)
      _output.writeStringCR("M  END");
}



